﻿//-----------------------------------------------------------------------
// <copyright file="ColorUtils.cs" company="cx studio">
//     Copyright (c) cx studio. All rights reserved.
// </copyright>
// <author>Xi Chen</author>
//-----------------------------------------------------------------------
namespace CentralFoveaLib.Helper
{
    using System;
    using CentralFoveaLib.ColorProcess;

    /// <summary>
    /// This is a color helper class.
    /// </summary>
    public class ColorUtils
    {
        /// <summary>
        /// Get the gray. 
        /// </summary>
        /// R * 0.299 + G * 0.587 + B * 0.114
        /// <param name="c">RGB color system.</param>
        /// <returns>The gray value.</returns>
        public static int GetGray(ColorRGB c)
        {
            double gray = (c.R * 0.299) + (c.G * 0.587) + (c.B * 0.114);
            return (int)gray;
        }

        /// <summary>
        /// Get the gray.   (R+G+B)/3
        /// </summary>
        /// <param name="c">RGB color system.</param>
        /// <returns>The gray value.</returns>
        public static int GetEGray(ColorRGB c)
        {
            return (int)((c.R + c.G + c.B) / 3);
        }

        /// <summary>
        /// Color is same.
        /// </summary>
        /// <param name="color">The first color.</param>
        /// <param name="color2">The second color.</param>
        /// <returns>If true.</returns>
        public static bool ColorIsSame(ColorRGB color, ColorRGB color2)
        {
            if (color.A == color2.A && color.R == color2.R && color.G == color2.G && color.B == color2.B)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Convert HSL to RGB system.
        /// </summary>
        /// <param name="hslColor">HSL color system.</param>
        /// <returns>RGB color system.</returns>
        public static ColorRGB HSL_RGB(ColorHSL hslColor)
        {
            int h = Convert.ToInt32(Convert.ToDecimal(hslColor.H) / 360 * 255);
            int s = Convert.ToInt32(Convert.ToDecimal(hslColor.S) / 100 * 255);
            int l = Convert.ToInt32(Convert.ToDecimal(hslColor.L) / 100 * 255);
            var color = new ColorRGB(0, 0, 0);
            if (s == 0)
            {
                color.R = 0;
                color.G = 0;
                color.B = 0;
            }

            decimal fractionalSector;
            decimal sectorNumber;
            decimal sectorPos;
            sectorPos = (Convert.ToDecimal(h) / 255 * 360) / 60;
            sectorNumber = Convert.ToInt32(Math.Floor(Convert.ToDouble(sectorPos)));
            fractionalSector = sectorPos - sectorNumber;

            decimal p;
            decimal q;
            decimal t;

            decimal r = 0;
            decimal g = 0;
            decimal b = 0;
            decimal ss = Convert.ToDecimal(s) / 255;
            decimal vv = Convert.ToDecimal(l) / 255;

            p = vv * (1 - ss);
            q = vv * (1 - (ss * fractionalSector));
            t = vv * (1 - (ss * (1 - fractionalSector)));

            switch (Convert.ToInt32(sectorNumber))
            {
                case 0:

                    r = vv;
                    g = t;
                    b = p;
                    break;

                case 1:
                    r = q;
                    g = vv;
                    b = p;
                    break;
                case 2:

                    r = p;
                    g = vv;
                    b = t;
                    break;
                case 3:

                    r = p;
                    g = q;
                    b = vv;
                    break;
                case 4:

                    r = t;
                    g = p;
                    b = vv;
                    break;
                case 5:

                    r = vv;
                    g = p;
                    b = q;
                    break;
            }

            color.R = Convert.ToByte(r * 255);
            color.G = Convert.ToByte(g * 255);
            color.B = Convert.ToByte(b * 255);
            return color;
        }

        /// <summary>
        /// Convert RGB color system to HSL.
        /// </summary>
        /// <param name="color">RGB color system.</param>
        /// <returns>HSL color system.</returns>
        public static ColorHSL RGB_HSL(ColorRGB color)
        {
            double r = color.R / 255.00;
            double g = color.G / 255.00;
            double b = color.B / 255.00;

            double max, min, diff, r_dist, g_dist, b_dist;
            double h, s, l;

            max = Math.Max(Math.Max(r, g), b);
            min = Math.Min(Math.Min(r, g), b);

            diff = max - min;

            l = (max + min) / 2.00 * 100.00;

            if (diff == 0)
            {
                h = 0;
                s = 0;
            }
            else
            {
                if (l < 50)
                {
                    s = diff / (max + min) * 100.00;
                }
                else
                {
                    s = diff / (2 - max - min) * 100.00;
                }

                r_dist = (max - r) / diff;
                g_dist = (max - g) / diff;
                b_dist = (max - b) / diff;

                h = b_dist - g_dist;

                if (r == max)
                {
                    h = b_dist - g_dist;
                }
                else if (g == max)
                {
                    h = 2 + r_dist - b_dist;
                }
                else if (b == max)
                {
                    h = 4 + g_dist - r_dist;
                }

                h *= 60;

                if (h < 0)
                {
                    h += 360;
                }

                if (h >= 360)
                {
                    h -= 360;
                }
            }

            return new ColorHSL((int)h, (int)s, (int)l);
        }

        /// <summary>
        /// Get the color name.
        /// </summary>
        /// <param name="hsl">The HSL color system.</param>
        /// <returns>Return color name.</returns>
        public static int GetColorName(ColorHSL hsl)
        {
            // H 是 18 degree
            int level = 0;
            if ((0 <= hsl.H && hsl.H <= 8) || (350 <= hsl.H && hsl.H <= 360))
            {
                level = 0;
            }
            else if (8 <= hsl.H && hsl.H < 350)
            {
                level = Convert.ToInt32((hsl.H - 8 - 1) / 18);
            }
            else
            {
                if (hsl.H < 0 || hsl.H > 360)
                {
                    throw new Exception();
                }
            }

            int lighteness = 0;
            if (0 <= hsl.L && hsl.L < 20)
            {
                lighteness = 0;
            }
            else if (20 <= hsl.L && hsl.L < 40)
            {
                lighteness = 1;
            }
            else if (40 <= hsl.L && hsl.L < 60)
            {
                lighteness = 2;
            }
            else if (60 <= hsl.L && hsl.L < 80)
            {
                lighteness = 3;
            }
            else if (80 <= hsl.L && hsl.L < 100)
            {
                lighteness = 4;
            }

            int s = 0;
            if (0 <= hsl.S && hsl.S < 20)
            {
                s = 1;
            }
            else if (20 <= hsl.S && hsl.S < 40)
            {
                s = 2;
            }
            else if (40 <= hsl.S && hsl.S < 60)
            {
                s = 3;
            }
            else if (60 <= hsl.S && hsl.S < 80)
            {
                s = 4;
            }
            else if (80 <= hsl.S && hsl.S < 100)
            {
                s = 5;
            }

            return (level * 5 * 5) + (lighteness * 5) + s;
        }
    }
}
